import logging
import os
import fnmatch
import random
import string
import json
import time
import urllib.parse
import openpyxl
from openpyxl import Workbook
from openpyxl import load_workbook
from openpyxl.styles import Alignment
from kafka import KafkaProducer
from datetime import datetime
import yaml
from typing import Any
import requests

# 设置日志配置
logger = logging.getLogger()
logger.setLevel(logging.INFO)

# 创建一个输出到文件的handler
file_handler = logging.FileHandler('../logs/createIndicator.log', mode='w')
file_handler.setLevel(logging.INFO)
file_handler.setFormatter(logging.Formatter('%(asctime)s %(levelname)s:%(message)s', datefmt='%Y-%m-%d %H:%M:%S'))

# 创建一个输出到控制台的handler
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)
console_handler.setFormatter(logging.Formatter('%(asctime)s %(levelname)s:%(message)s', datefmt='%Y-%m-%d %H:%M:%S'))

# 将handler添加到logger
logger.addHandler(file_handler)
logger.addHandler(console_handler)


def extract_names_from_yaml(yaml_file_path, names_set):
    # 打开并读取 YAML 文件
    with open(yaml_file_path, 'r') as file:
        data = yaml.safe_load(file)

        # 定义一个递归函数来遍历数据
        def extract_names(obj):
            if isinstance(obj, dict):  # 如果条目是字典类型
                for key, value in obj.items():
                    if key == 'name':  # 检查键是否为 'name'
                        names_set.add(value)  # 添加到集合中
                    else:
                        extract_names(value)  # 递归搜索
            elif isinstance(obj, list):  # 如果条目是列表类型
                for item in obj:
                    extract_names(item)  # 对列表中每个条目递归搜索

        # 开始遍历 YAML 数据
        extract_names(data)


# 发送消息到 Kafka 队列
def send_message_to_kafka(brokers_hosts, topic, data, loop_count=None, loop_interval=None):
    producer = KafkaProducer(bootstrap_servers=brokers_hosts, api_version=(2, 1))
    # 判断第一次发送是否在1分钟内最后10秒，如果当前时间在最后10秒，则等待到下一个分钟再发送
    current_time = time.localtime()
    if current_time.tm_sec > 50:
        logging.info("等待下一个分钟...")
        for i in range(10, 0, -1):
            logging.info(f"倒数计时: {i}秒")
            time.sleep(1)

    # 循环发送消息
    if loop_count and loop_interval:
        for count in range(1, loop_count + 1):
            current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            current_timestamp = int(time.time() * 1000)

            # 替换时间与时间戳
            data["data"]["requestTime"] = current_time
            data["data"]["requestTimestamp"] = current_timestamp
            data["data"]["responseTime"] = current_time
            data["data"]["responseTimestamp"] = current_timestamp

            # 替换ID
            data["data"]["id"] = generate_random_string(32)
            data = json.dumps(data)
            producer.send(topic, key=data.encode('utf-8'), value=data.encode('utf-8'), partition=0)
            producer.flush()
            logging.info(f"已发送第 {count} 条报文")
            # print(data)
            data = json.loads(data)
            time.sleep(loop_interval)
    else:
        current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        current_timestamp = int(time.time() * 1000)
        # 替换时间与时间戳
        data["data"]["requestTime"] = current_time
        data["data"]["requestTimestamp"] = current_timestamp
        data["data"]["responseTime"] = current_time
        data["data"]["responseTimestamp"] = current_timestamp

        # 替换ID
        data["data"]["id"] = generate_random_string(32)
        data = json.dumps(data)
        producer.send(topic, key=data.encode('utf-8'), value=data.encode('utf-8'), partition=0)  # 指定分区
        producer.flush()

    # 关闭 KafkaProducer 实例
    producer.close()

    logging.info("已报文发送完毕")


# 生成txt报文文档
def save_file(pwd, data):
    with open(pwd, 'w') as file:
        json.dump(data, file, indent=4)
    print("已更新报文")

    file = open(pwd, 'r')
    data = file.read()
    file.close()
    return data


# 自动生成报文ID 32位随机大写字母+数字
def generate_random_string(length=32):
    characters = string.ascii_uppercase + string.digits
    random_string = ''.join(random.choice(characters) for _ in range(length))
    return random_string


# 替换报文时间戳为当前时间
def upate_meassage_time(data):
    # 替换请求响应时间与时间戳
    current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    current_timestamp = int(time.time() * 1000)
    data["data"]["requestTime"] = current_time
    data["data"]["requestTimestamp"] = current_timestamp
    data["data"]["responseTime"] = current_time
    data["data"]["responseTimestamp"] = current_timestamp
    return data


# 替换报文ID为随机ID
def upate_meassage_id(data):
    # 替换报文ID
    characters = string.ascii_uppercase + string.digits
    ID = ''.join(random.choice(characters) for _ in range(32))
    data["data"]["id"] = ID
    return data


# 替换报文ip地址为随机ip+端口
def generate_ip_port():
    ip = '.'.join(str(random.randint(0, 255)) for _ in range(4))
    port = random.randint(1, 65535)
    data["data"]["requestIp"] = f"{ip}:{port}"


# 适配API资产的报文发送
def send_message_to_kafka2(brokers_hosts, topic, data, loop_count=None, loop_interval=None):
    producer = KafkaProducer(bootstrap_servers=brokers_hosts, api_version=(2, 1))

    # 循环发送消息
    if loop_count and loop_interval:
        for count in range(1, loop_count + 1):
            current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            current_timestamp = int(time.time() * 1000)

            # 替换时间与时间戳
            data["message"]["data"]["requestTime"] = current_time
            data["message"]["data"]["requestTimestamp"] = current_timestamp
            data["message"]["data"]["responseTime"] = current_time
            data["message"]["data"]["responseTimestamp"] = current_timestamp

            # 替换ID
            data["message"]["data"]["id"] = generate_random_string(32)
            data = json.dumps(data)
            producer.send(topic, key=data.encode('utf-8'), value=data.encode('utf-8'), partition=0)
            producer.flush()
            print(f"已发送第 {count} 条报文")
            data = json.loads(data)
            time.sleep(loop_interval)
    else:
        current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        current_timestamp = int(time.time() * 1000)
        # 替换时间与时间戳
        data["message"]["data"]["requestTime"] = current_time
        data["message"]["data"]["requestTimestamp"] = current_timestamp
        data["message"]["data"]["responseTime"] = current_time
        data["message"]["data"]["responseTimestamp"] = current_timestamp

        # 替换ID
        data["message"]["data"]["id"] = generate_random_string(32)
        data = json.dumps(data)
        producer.send(topic, key=data.encode('utf-8'), value=data.encode('utf-8'), partition=0)  # 指定分区
        producer.flush()

    # 关闭 KafkaProducer 实例
    producer.close()
    # print(data)
    logging.info("成功----已发送报文到kafka")


def send_message_to_kafka3(brokers_hosts, topic, data, loop_count=None, loop_interval=None):
    producer = KafkaProducer(bootstrap_servers=brokers_hosts, api_version=(2, 1))

    # 循环发送消息
    if loop_count and loop_interval:
        for count in range(1, loop_count + 1):
            current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            current_timestamp = int(time.time() * 1000)

            # 替换时间与时间戳
            data["message"]["data"]["requestTime"] = current_time
            data["message"]["data"]["requestTimestamp"] = current_timestamp
            data["message"]["data"]["responseTime"] = current_time
            data["message"]["data"]["responseTimestamp"] = current_timestamp

            # 替换ID
            data["message"]["data"]["id"] = generate_random_string(32)
            data = json.dumps(data)
            producer.send(topic, key=data.encode('utf-8'), value=data.encode('utf-8'), partition=0)
            producer.flush()
            print(f"已发送第 {count} 条报文")
            data = json.loads(data)
            time.sleep(loop_interval)
    else:
        current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        current_timestamp = int(time.time() * 1000)
        # 替换时间与时间戳
        data["message"]["data"]["requestTime"] = current_time
        data["message"]["data"]["requestTimestamp"] = current_timestamp
        data["message"]["data"]["responseTime"] = current_time
        data["message"]["data"]["responseTimestamp"] = current_timestamp

        # 替换ID
        data["message"]["data"]["id"] = generate_random_string(32)
        data = json.dumps(data)
        producer.send(topic, key=data.encode('utf-8'), value=data.encode('utf-8'), partition=0)  # 指定分区
        producer.flush()

    # 关闭 KafkaProducer 实例
    producer.close()
    # print(data)
    logging.info("成功----已发送报文到kafka")


def read_yaml(yaml_file_path: str) -> Any:
    yaml_file_path = "/config/config.yaml"
    """
    参数:
    - yaml_file_path: YAML 文件的路径字符串。
    返回值:
    - 返回解析后的 YAML 文件内容。
    """
    try:
        with open(yaml_file_path, 'r') as file:
            return yaml.safe_load(file)
    except FileNotFoundError:
        logging.info(f"错误：未找到文件 {yaml_file_path}")
        return None
    except yaml.YAMLError as exc:
        logging.info(f"错误：解析 YAML 文件时发生错误 - {exc}")
        return None


# 登陆API平台，获取token
def login_keep_token(env):
    # 读取配置文件
    with open('../config/config.yaml', 'r') as f:
        config = yaml.safe_load(f)

    # 获取配置参数
    url = config['environments'][env]['uri']
    admin_name = config['environments'][env]['adminName']
    admin_password = config['environments'][env]['adminPassword']

    # 构造请求体
    payload = {
        'name': admin_name,
        'password': admin_password,
        'publicKeyId': 0
    }
    data = json.dumps(payload)
    # print(data)
    # 发送请求
    response = requests.post(url, data=data, headers={'Content-Type': 'application/json', 'version': '2.0'})
    # print(response.text)
    # 解析响应体，提取token的值
    response_json = response.json()
    if response_json.get('code') != '200':
        logging.info("失败----未能成功获取token")
        raise Exception(f"失败----未能成功获取token，响应信息：{response.text}")
    token = response_json.get('data', {}).get('token')
    # print(token)
    # 将token写入yml文件
    with open('../data/token.yml', 'w') as f:
        yaml.safe_dump({'token': token}, f)

    # 输出响应结果
    logging.info("成功----已提取到token")


# 创建风险策略
def add_risk_configs(language, env, indicator):
    # 读取配置文件
    with open('../config/config.yaml', 'r') as f:
        config = yaml.safe_load(f)

    with open('../data/token.yml', 'r') as f:
        token = yaml.safe_load(f)

    with open('../config/riskConfigs.yaml', 'r') as f:
        riskCongis = yaml.safe_load(f)

    # 获取配置参数
    url = config['environments'][env]['host'] + 'api/asset/risks/strategies'
    Authorization = token['token']
    riskName = riskCongis[language][indicator]['name'] + '-' + datetime.now().strftime("%H:%M:%S")
    level = random.choice(['high', 'mid', 'low'])
    indicatorId = riskCongis[language][indicator]['indicatorId']
    indicatorName = riskCongis[language][indicator]['indicatorName']

    # print(url)

    # 构造请求头
    headers = {'Content-Type': 'application/json',
               'Authorization': Authorization,
               'Version': '2.0'
               }
    # print(headers)
    # 构造请求体
    payload = {
        "name": riskName,
        "apis": [".*"],
        "subject": "",
        "level": level,
        "recordPeriod": "MINUTES",
        "relations": [{
            "indicatorId": indicatorId,
            "indicatorName": indicatorName,
            "reviewMethod": "GTE",
            "threshold": 1
        }],
        "rule": "any",
        "status": "enabled"
    }

    # 发送请求
    response = requests.post(url, json=payload, headers=headers)
    response_json = response.json()
    if response_json.get('code') != '200':
        logging.info(f"失败----未能成功获取riskId，响应信息：{response.text}")
        raise Exception(f"失败----未能成功获取riskId，响应信息：{response.text}")
    # print(response.text)

    # 提取id 存入 token.yml
    response_json = response.json()
    riskId = response_json.get('data', {}).get('id')
    # print(riskId)

    with open('../data/riskId.yml', 'w') as f:
        yaml.safe_dump({'riskId': riskId}, f)
        yaml.safe_dump({'riskName': riskName}, f)

    # 输出响应结果
    logging.info("成功----创建风险策略——" + riskName)
    logging.info("成功----已提取到riskId")


# 删除风险策略
def del_risk_configs(env):
    # 读取token
    with open('../config/config.yaml', 'r') as f:
        config = yaml.safe_load(f)
    with open('../data/token.yml', 'r') as f:
        token = yaml.safe_load(f)
    with open('../data/riskId.yml', 'r') as f:
        risk = yaml.safe_load(f)

    # 获取配置参数
    riskId = risk['riskId']
    url = config['environments'][env]['host'] + 'api/asset/risks/strategies/' + riskId
    Authorization = token['token']

    # print(url)

    # 构造请求头
    headers = {'Content-Type': 'application/json',
               'Authorization': Authorization,
               'Version': '2.0',
               'X-Request-Method': 'DELETE'
               }
    # print(headers)

    # 发送请求
    response = requests.post(url, headers=headers)
    # print(response.text)
    if response.status_code == 200:
        logging.info('成功----风险策略已删除')
    else:
        logging.info('失败----风险策略删除未成功')


# 删除弱点定义
def del_weakness_configs(env):
    # 读取token
    with open('../config/config.yaml', 'r') as f:
        config = yaml.safe_load(f)
    with open('../data/token.yml', 'r') as f:
        token = yaml.safe_load(f)
    with open('../data/weaknessId.yml', 'r') as f:
        weakness = yaml.safe_load(f)

    # 获取配置参数
    riskId = weakness['weaknessId']
    url = config['environments'][env]['host'] + 'api/asset/weakness/definition/' + riskId
    Authorization = token['token']

    # print(url)

    # 构造请求头
    headers = {'Content-Type': 'application/json',
               'Authorization': Authorization,
               'Version': '2.0',
               'X-Request-Method': 'DELETE'
               }
    # print(headers)

    # 发送请求
    response = requests.post(url, headers=headers)
    # print(response.text)
    if response.status_code == 200:
        logging.info('成功----弱点定义已删除')
    else:
        logging.info('失败----弱点定义删除未成功')


# 创建弱点定义
def add_weakness_configs(language, env, indicator):
    # 读取配置文件
    with open('../config/config.yaml', 'r') as f:
        config = yaml.safe_load(f)

    with open('../data/token.yml', 'r') as f:
        token = yaml.safe_load(f)

    with open('../config/weaknessConfigs.yaml', 'r') as f:
        weaknessCongis = yaml.safe_load(f)

    # 获取配置参数
    url = config['environments'][env]['host'] + 'api/asset/weakness/definition'
    Authorization = token['token']
    weaknessName = weaknessCongis[language][indicator]['name'] + '-' + datetime.now().strftime("%H:%M:%S")
    level = random.choice(['nhigh', 'mid', 'low'])
    indicatorId = weaknessCongis[language][indicator]['indicatorId']

    # 构造请求头
    headers = {'Content-Type': 'application/json',
               'Authorization': Authorization,
               'Version': '2.0'
               }
    # print(headers)
    # 构造请求体
    payload = {
        "name": weaknessName,
        "level": level,
        "indicatorId": indicatorId,
        "status": "enabled"
    }

    # 发送请求
    response = requests.post(url, json=payload, headers=headers)
    response_json = response.json()
    if response_json.get('code') != '200':
        raise Exception(f"失败----未能成功获取weaknessId，响应信息：{response.text}")
    # print(response.text)

    # 提取id 存入 token.yml
    response_json = response.json()
    weaknessId = response_json.get('data', {}).get('id')
    # print(riskId)

    with open('../data/weaknessId.yml', 'w') as f:
        yaml.safe_dump({'weaknessId': weaknessId}, f)
        yaml.safe_dump({'weaknessName': weaknessName}, f)

    # 输出响应结果
    logging.info("成功----创建弱点定义——" + weaknessName)
    logging.info("成功----已提取到weaknessId")


# 查询风险
def check_risk(env):
    # 读取配置文件
    with open('../config/config.yaml', 'r') as f:
        config = yaml.safe_load(f)

    with open('../data/token.yml', 'r') as f:
        token = yaml.safe_load(f)

    with open('../data/riskId.yml', 'r') as f:
        risk = yaml.safe_load(f)

    # 获取配置参数
    riskName = risk['riskName']
    url = config['environments'][env]['host'] + 'api/asset/risk/events?'
    Authorization = token['token']
    # print(url)
    params = {'size': 10, 'filter': {}, 'page': 1, 'searchKey': riskName}
    url = url + urllib.parse.urlencode(params)

    # 构造请求头
    headers = {'Content-Type': 'application/json',
               'Authorization': Authorization,
               'Version': '2.0'
               }

    # 发送请求
    response = requests.get(url, headers=headers)
    # print(response.text)
    try:
        wb = load_workbook('../filesOutput/指标触发结果.xlsx')
        ws = wb.active
    except FileNotFoundError:
        wb = Workbook()
        ws = wb.active
        ws['A1'] = '指标名称'
        ws['B1'] = '触发时间'
        ws['C1'] = '是否成功'

    # 在现有数据后面追加新数据
    response_json = response.json()
    if response_json.get('code') == '200' and response_json.get('data', {}).get('page', {}).get('total') == 1:
        logging.info('成功----已查询到风险，指标触发成功')
        ws.append([riskName, datetime.now().strftime('%Y-%m-%d %H:%M:%S'), '成功'])
    else:
        logging.info('失败----未查询到风险，指标触发失败')
        ws.append([riskName, datetime.now().strftime('%Y-%m-%d %H:%M:%S'), '失败'])

    wb.save('../filesOutput/指标触发结果.xlsx')


def check_weakness(env):
    # 读取配置文件
    with open('../config/config.yaml', 'r') as f:
        config = yaml.safe_load(f)

    with open('../data/token.yml', 'r') as f:
        token = yaml.safe_load(f)

    with open('../data/weaknessId.yml', 'r') as f:
        weak = yaml.safe_load(f)

    # 获取配置参数
    weaknessName = weak['weaknessName']
    url = config['environments'][env]['host'] + 'api/asset/weakness/event?'
    Authorization = token['token']
    # print(url)
    params = {'size': 10, 'filter': {}, 'page': 1, 'searchKey': weaknessName}
    url = url + urllib.parse.urlencode(params)

    # 构造请求头
    headers = {'Content-Type': 'application/json',
               'Authorization': Authorization,
               'Version': '2.0'
               }

    # 发送请求
    response = requests.get(url, headers=headers)
    # print(response.text)

    # 结果写入 Execl文件
    try:
        wb = load_workbook('../filesOutput/指标触发结果.xlsx')
        ws = wb.active
    except FileNotFoundError:
        wb = Workbook()
        ws = wb.active
        ws['A1'] = '指标名称'
        ws['B1'] = '触发时间'
        ws['C1'] = '是否成功'

    # 在现有数据后面追加新数据
    response_json = response.json()
    if response_json.get('code') == '200' and response_json.get('data', {}).get('page', {}).get('total') == 1:
        logging.info('成功----已查询到弱点，指标触发成功')
        ws.append([weaknessName, datetime.now().strftime('%Y-%m-%d %H:%M:%S'), '成功'])
    else:
        logging.info('失败----未查询到弱点，指标触发失败')
        ws.append([weaknessName, datetime.now().strftime('%Y-%m-%d %H:%M:%S'), '失败'])

    wb.save('../filesOutput/指标触发结果.xlsx')


def make_assets(env, indicator, loop_count=None, loop_interval=None):
    # 读取配置文件
    with open('../config/config.yaml', 'r') as f:
        config = yaml.safe_load(f)

    # 尝试读取risk对应的文件路径
    indicator_message_path = '../data/riskMessage/' + indicator + '.txt'
    try:
        with open(indicator_message_path, 'r') as file:
            data = file.read()
            data_dict = json.loads(data)
    except FileNotFoundError:
        # 如果找不到risk对应的文件，则尝试读取weakness对应的文件路径
        indicator_message_path = '../data/weaknessMessage/' + indicator + '.txt'
        with open(indicator_message_path, 'r') as file:
            data = file.read()
            data_dict = json.loads(data)
    # print(data_dict)
    # 提取到参数
    brokers_hosts = config["environments"][env]["zookeeper"]
    topic = config["environments"][env]["topic"]
    # print(brokers_hosts)
    # print(topic)

    # 向指定目标发送报文
    send_message_to_kafka2(brokers_hosts=brokers_hosts, topic=topic, data=data_dict, loop_count=loop_count,
                           loop_interval=loop_interval)


#  发送多次报文生成指标
def make_assets_multi_message(env, indicator, loop_count=None, loop_interval=None):
    # 读取配置文件
    with open('../config/config.yaml', 'r') as f:
        config = yaml.safe_load(f)

    # 提取到参数
    brokers_hosts = config["environments"][env]["zookeeper"]
    topic = config["environments"][env]["topic"]

    # 设置文件夹路径
    risk_path = '../data/riskMessage/'
    weakness_path = '../data/weaknessMessage/'

    # 结合两个目录查找文件
    directories = [risk_path, weakness_path]
    for directory in directories:
        for file in os.listdir(directory):
            # 如果文件名匹配指示器，则读取并发送报文
            if fnmatch.fnmatch(file, f'*{indicator}*.txt'):
                file_path = os.path.join(directory, file)
                try:
                    with open(file_path, 'r') as message_file:
                        data = message_file.read()
                        data_dict = json.loads(data)
                    # 向指定目标发送报文
                    send_message_to_kafka2(brokers_hosts=brokers_hosts, topic=topic, data=data_dict,
                                           loop_count=loop_count, loop_interval=loop_interval)
                except FileNotFoundError:
                    logging.info(f"报文文件 {file} 在 {directory}下没有发现")
                except json.JSONDecodeError:
                    logging.info(f"json序列化错误 {file}")


# 触发指标 适用于仅发送1次报文
def create_indicator_risk(env, indicator, interval_time, loop_count=None, loop_interval=None):
    logging.info("============生成指标开始============")
    if any(character for character in indicator if character.isalpha()):  # 检查 indicator 中是否包含汉字
        language = 'zh'
    else:
        language = 'en'

    login_keep_token(env)
    add_risk_configs(language, env, indicator)
    make_assets(env, indicator)
    logging.info("等待----资产生成中...")
    time.sleep(interval_time)
    check_risk(env)
    del_risk_configs(env)
    logging.info("============生成指标结束============")


# 触发指标 适用于发送多次报文，或者指定不同报文
def create_indicator_multi_risk(env, indicator, interval_time, loop_count=None, loop_interval=None):
    logging.info("============生成指标开始============")
    if any(character for character in indicator if character.isalpha()):  # 检查 indicator 中是否包含汉字
        language = 'zh'
    else:
        language = 'en'

    login_keep_token(env)
    add_risk_configs(language, env, indicator)
    make_assets_multi_message(env, indicator)
    logging.info("等待----资产生成中...")
    time.sleep(interval_time)
    check_risk(env)
    del_risk_configs(env)
    logging.info("============生成指标结束============")


def create_indicator_weakness(env, indicator, interval_time, loop_count=None, loop_interval=None):
    logging.info("============生成指标开始============")
    if any(character for character in indicator if character.isalpha()):  # 检查 indicator 中是否包含汉字
        language = 'zh'
    else:
        language = 'en'

    login_keep_token(env)
    add_weakness_configs(language, env, indicator)
    make_assets(env, indicator)
    logging.info("等待----资产生成中...")
    time.sleep(interval_time)
    check_weakness(env)
    del_weakness_configs(env)
    logging.info("============生成指标结束============")


# 创建指标
def create_indicator(env, indicator, interval_time, loop_count=None, loop_interval=None, multi=None):
    if any(character for character in indicator if character.isalpha()):  # 检查 indicator 中是否包含汉字
        language = 'zh'
    else:
        language = 'en'

    risks = set()
    extract_names_from_yaml('../config/riskConfigs.yaml', risks)
    weaknesses = set()
    extract_names_from_yaml('../config/weaknessConfigs.yaml', weaknesses)
    # print(risks)
    # print(weaknesses)
    if indicator in risks:
        if multi is not None:
            # 如果 multi 不为 None，调用新的方法
            create_indicator_multi_risk(env, indicator, interval_time, loop_count, loop_interval)
        else:
            create_indicator_risk(env, indicator, interval_time)
        # 判断指标是否同时属于弱点
    elif indicator in weaknesses:
        create_indicator_weakness(env, indicator, interval_time)
    else:
        # 如果指标不在风险和弱点中，记录日志并抛出异常
        logging.info("未找到对应指标，检查拼写或项目指标配置")
        raise Exception(f"未找到对应指标，检查拼写或项目指标配置")
